home *** CD-ROM | disk | FTP | other *** search
- /*
- * The Amiga version of raypaint will open a 16 gray level black & white
- * screen or a 8/32 color screen (depending on whether hires is required for
- * the requested screen width or not) of the appropriate size. It will use
- * hires, lace, overscan, or autoscroll to accommodate the entire picture.
- * Both PAL and NTSC machines should be catered for.
- *
- * If you have a three button mouse, the middle button should work as
- * described in the README file. If you do not, pressing both mouse
- * buttons will do the same thing (remember to deactivate any background
- * programs like DMouse that use pressing both mouse buttons to flip
- * between screens, etc). Some of these programs can be fooled by pressing
- * the right mouse button first.
- *
- * The code will only work on version 2.0 or higher of AmigaDOS.
- *
- * Send comments and bug reports to:
- *
- * Kriton Kyrimis UUCP: pythia!theseas!kriton!kyrimis
- * INTERNET: kyrimis@theseas.ntua.gr
- */
-
- #include <stdio.h>
- #include <exec/types.h>
- #include <exec/nodes.h>
- #include <exec/lists.h>
- #include <exec/ports.h>
- #include <dos/dos.h>
- #include <intuition/intuition.h>
- #include <intuition/classes.h>
- #include <graphics/gfxbase.h>
- #include <graphics/view.h>
- #include <graphics/graphint.h>
- #include <utility/tagitem.h>
-
- #ifdef __SASC
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <proto/intuition.h>
- #include <proto/graphics.h>
- #endif
- #ifdef __GNUC__
- #include <inline/exec.h>
- #include <inline/dos.h>
- #include <inline/intuition.h>
- #include <inline/graphics.h>
- #endif
-
- #define MAX_X 362
- #define MAX_Y_NTSC 241
- #define MAX_Y_PAL 283
-
- #define MAPX(x) ((x) + offsetx)
- #define MAPY(y) (sh - (y) - 1 - offsety)
-
- #define UNMAPX(x) ((x) - offsetx)
- #define UNMAPY(y) (sh - (y) - 1 - offsety)
-
- static void Cleanup(void);
- static int IsPAL(void);
- static int CalcWidth(int);
- static int CalcHeight(int, int);
- static void MouseHandler(void);
- static void HandleIDCMP(void);
- static void StripIntuiMessages(struct MsgPort *, struct Window *);
- static struct MsgPort *CreatePort(UBYTE *, LONG);
- static void DeletePort(struct MsgPort *);
- static void SetupGrayMap(void);
- static void SetupColorMap(int);
-
- struct GfxBase *GfxBase = NULL;
- struct IntuitionBase *IntuitionBase = NULL;
-
- static struct NewScreen screen = {
- 0, 0, 0, 0, 0, 0, 1, 0, AUTOSCROLL | CUSTOMSCREEN, NULL, NULL, NULL, NULL
- };
-
- UWORD DriPens[] = { (UWORD)~0 };
-
- static struct TagItem ScreenTags[] = {
- #define DISPIDTAG 0
- {SA_DisplayID, NULL},
- {SA_Overscan, OSCAN_VIDEO},
- {SA_Pens, (ULONG)DriPens},
- {TAG_DONE, NULL}
- };
-
- static struct Image img = {
- 0, 0, 10, 10, 0, NULL, 0, 0, NULL
- };
-
- static struct Gadget CloseGadget = {
- NULL, 0, 0, 10, 10, GFLG_GADGHCOMP | GFLG_GADGIMAGE, GACT_RELVERIFY,
- GTYP_BOOLGADGET, (APTR)&img, NULL, NULL, 0, NULL, 1, NULL
- };
-
- static struct NewWindow window = {
- 0, 0, 0, 0, 0, 1, 0,
- WFLG_SMART_REFRESH | WFLG_BACKDROP | WFLG_BORDERLESS | WFLG_RMBTRAP,
- &CloseGadget, NULL, NULL, NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN
- };
-
- static volatile struct Screen *s = NULL;
- static volatile struct Window *w = NULL;
- static struct RastPort *rp = NULL;
- static struct ViewPort *vp = NULL;
-
- static int maxx, maxy, sw, sh, offsetx, offsety;
- static volatile int Done = 0;
- static struct Task *HandlerTask = NULL;
- static volatile int LMB=0;
- static volatile int MMB=0;
- static volatile int RMB=0;
- static volatile struct MsgPort *HandlerPort;
-
- static int gray, max_colors;
-
- void
- GraphicsInit(int xsize, int ysize, char *name, int gray)
- {
- BYTE pal;
-
- atexit(Cleanup);
- if ((GfxBase =
- (struct GfxBase *) OpenLibrary ("graphics.library", 0L)) == NULL){
- fprintf (stderr, "Can't open graphics.library\n");
- Cleanup();
- exit(RETURN_FAIL);
- }
-
- if ((IntuitionBase =
- (struct IntuitionBase *) OpenLibrary ("intuition.library", 0L)) == NULL){
- fprintf (stderr, "Can't open intuition.library\n");
- Cleanup();
- exit(RETURN_FAIL);
- }
-
- pal = IsPAL();
- maxx = xsize - 1;
- maxy = ysize - 1;
- sw = CalcWidth(xsize);
- screen.Width = sw;
- sh = CalcHeight(ysize, pal);
- screen.Height = sh;
- screen.DefaultTitle = name;
- offsetx = (sw - xsize) / 2;
- offsety = (sh - ysize) / 2;
- if (pal) {
- screen.ViewModes =
- ((sh > MAX_Y_PAL) ? LACE : 0) | ((sw > MAX_X) ? HIRES : 0);
- }else{
- screen.ViewModes =
- ((sh > MAX_Y_NTSC) ? LACE : 0) | ((sw > MAX_X) ? HIRES : 0);
- }
- window.Width = sw, window.Height = sh;
- ScreenTags[DISPIDTAG].ti_Data = screen.ViewModes;
- if (pal) {
- ScreenTags[DISPIDTAG].ti_Data |= PAL_MONITOR_ID;
- }else{
- ScreenTags[DISPIDTAG].ti_Data |= NTSC_MONITOR_ID;
- }
- if (gray) {
- screen.Depth = 4;
- }else{
- if (screen.ViewModes & HIRES) {
- screen.Depth = 3;
- }else{
- screen.Depth = 5;
- }
- }
- if ((s = OpenScreenTagList (&screen, ScreenTags)) == NULL){
- fprintf (stderr, "Can't open screen 1\n");
- Cleanup();
- exit(RETURN_FAIL);
- }
- ShowTitle (s, FALSE);
- window.Screen = s;
- if ((w = OpenWindow (&window)) == NULL){
- fprintf (stderr, "Can't open window\n");
- Cleanup();
- exit(RETURN_FAIL);
- }
- vp = &(s->ViewPort);
- rp = w->RPort;
-
- if (gray) {
- SetupGrayMap();
- }else{
- SetupColorMap(screen.Depth);
- }
-
- HandlerTask =
- CreateTask("Raypaint Mouse Handler", 1, (APTR)MouseHandler, 10000);
- }
-
- static void
- SetupGrayMap()
- {
- int i;
-
- gray = 1;
- for (i=0; i<16; i++) {
- SetRGB4 (vp, i, i, i, i);
- }
- }
-
- static void
- SetupColorMap(int depth)
- {
- int col;
- int r, g, b, red, green, blue;
- double one_over_gamma = 0.4;
-
- gray = 0;
- if (depth == 3) {
- max_colors = 2;
- }else{
- max_colors = 3;
- }
- col = 0;
- for (r = 0; r < max_colors; ++r) {
- red = 15 * r / (max_colors-1);
- for (g = 0; g < max_colors; ++g) {
- green = 15 * g / (max_colors-1);
- for (b = 0; b < max_colors; ++b) {
- blue = 15 * b / (max_colors-1);
- SetRGB4 (vp, col++, red, green, blue);
- }
- }
- }
- }
-
- static int
- IsPAL(void)
- {
- struct Screen *s;
- ULONG mode;
-
- s = LockPubScreen("Workbench");
- mode = GetVPModeID(&(s->ViewPort));
- UnlockPubScreen(NULL, s);
- if ((mode & PAL_MONITOR_ID) == PAL_MONITOR_ID){
- return TRUE;
- }
- if ((mode & NTSC_MONITOR_ID) == NTSC_MONITOR_ID){
- return FALSE;
- }
- /* Used to be this simple... */
- return (GfxBase->DisplayFlags & PAL) ? TRUE : FALSE;
- }
-
- static int
- CalcWidth(int width)
- {
- if (width <= 320) return 320;
- if (width <= MAX_X) return width;
- if (width <= 640) return 640;
- return width;
- }
-
- static int
- CalcHeight(int height, int pal)
- {
- if (pal) {
- if (height <= 256) return 256;
- if (height <= MAX_Y_PAL) return height;
- if (height <= 512) return 512;
- return height;
- }else{
- if (height <= 200) return 200;
- if (height <= MAX_Y_NTSC) return height;
- if (height <= 400) return 400;
- return height;
- }
- }
-
- /*
- * Draw the pixel at (xp, yp) in the color given by the rgb-triple,
- * 0 indicating 0 intensity, 255 max intensity.
- */
- void
- GraphicsDrawPixel(int xp, int yp, unsigned char color[3])
- {
- int val;
-
- if (Done) {
- Cleanup();
- exit(RETURN_OK);
- }
-
- if (gray) {
- val = (((0.35*(double)(color[0]) +
- 0.55*(double)(color[1]) +
- 0.10*(double)(color[2])) * 15.0) / 255.0) + 0.5;
- }else{
- val = color[0] / 255.0 * (max_colors-1) + 0.5;
- val *= max_colors;
- val += color[1] / 255.0 * (max_colors-1) + 0.5;
- val *= max_colors;
- val += color[2] / 255.0 * (max_colors-1) + 0.5;
- }
- SetAPen(rp, val);
- WritePixel(rp, MAPX(xp), MAPY(yp));
- }
-
- /*
- * Draw the rect with lower left corner (xp, yp) and upper right
- * corner (xp+ys, yp+ys). The colors of the l-l, l-r, u-r, and u-l
- * corners are given as arrays of unsigned chars as above.
- */
- void
- GraphicsDrawRectangle(int xp, int yp, int xs, int ys,
- unsigned char ll[3], unsigned char lr[3],
- unsigned char ur[3], unsigned char ul[3])
- {
- int val;
-
- if (Done) {
- Cleanup();
- exit(RETURN_OK);
- }
- if (gray) {
- val = (((0.35*(double)(ll[0]) +
- 0.55*(double)(ll[1]) +
- 0.10*(double)(ll[2])) * 15.0) / 255.0) + 0.5;
- }else{
- val = ll[0] / 255.0 * (max_colors-1) + 0.5;
- val *= max_colors;
- val += ll[1] / 255.0 * (max_colors-1) + 0.5;
- val *= max_colors;
- val += ll[2] / 255.0 * (max_colors-1) + 0.5;
- }
- SetAPen(rp, val);
- RectFill(rp, MAPX(xp), MAPY(yp+ys), MAPX(xp+xs), MAPY(yp));
- }
-
- int
- GraphicsRedraw(void)
- {
- /* This is a SMART_REFRESH window;
- We don't have to worry about redrawing it */
- return 0;
- }
-
- void
- GraphicsGetMousePos(int *x, int *y)
- {
- *x = UNMAPX(w->MouseX);
- *y = UNMAPY(w->MouseY);
- if (*x < 0) {
- *x = 0;
- }
- if (*x > maxx) {
- *x = maxx;
- }
- if (*y < 0) {
- *y = 0;
- }
- if (*y > maxy) {
- *y = maxy;
- }
- }
-
- int
- GraphicsLeftMouseEvent(void)
- {
- return LMB;
- }
-
- int
- GraphicsRightMouseEvent(void)
- {
- return RMB;
- }
-
- int
- GraphicsMiddleMouseEvent(void)
- {
- return MMB || (LMB && RMB);
- }
-
- static void
- Cleanup(void)
- {
- if (HandlerTask) {
- Signal(HandlerTask, 1 << HandlerPort->mp_SigBit);
- Delay(2);
- HandlerTask = NULL;
- }
- if (w) {
- CloseWindow(w);
- w = NULL;
- }
- if (s) {
- CloseScreen(s);
- s = NULL;
- }
- if (GfxBase) {
- CloseLibrary((struct Library *)GfxBase);
- }
- if (IntuitionBase) {
- CloseLibrary ((struct Library *)IntuitionBase);
- }
- }
-
- static void
- MouseHandler(void)
- {
- ULONG winsignalmask, portsignalmask, signals;
- struct MsgPort *IDCMPPort;
- struct IntuitionBase *IntuitionBase;
-
- IntuitionBase =
- (struct IntuitionBase *) OpenLibrary ("intuition.library", 0L);
- IDCMPPort = CreatePort("RayPaint IDCMP Port", 0);
- w->UserPort = IDCMPPort;
- ModifyIDCMP(w, IDCMP_GADGETUP | IDCMP_MOUSEBUTTONS);
-
- HandlerPort = CreatePort("RayPaint Handler Port", 0);
-
- for(;;){
- winsignalmask = 1L << w->UserPort->mp_SigBit;
- portsignalmask = 1L << HandlerPort->mp_SigBit;
-
- signals = Wait(winsignalmask | portsignalmask);
- if (signals & winsignalmask) {
- HandleIDCMP();
- }
- if (signals & portsignalmask){
- Forbid();
- StripIntuiMessages(w->UserPort, w);
- w->UserPort = NULL;
- ModifyIDCMP(w, 0);
- Permit();
- DeletePort(IDCMPPort);
- DeletePort(HandlerPort);
- CloseLibrary ((struct Library *)IntuitionBase);
- Done = 1;
- return;
- }
- }
- }
-
- static void
- HandleIDCMP(void)
- {
- struct IntuiMessage *message;
- ULONG class;
- USHORT code;
-
- while (message = (struct IntuiMessage *)GetMsg(w->UserPort)) {
- class = message->Class;
- code = message->Code;
-
- switch(class) {
- case IDCMP_GADGETUP:
- Done = 1;
- break;
- case IDCMP_MOUSEBUTTONS:
- switch(code) {
- case SELECTUP:
- LMB = 0;
- break;
- case SELECTDOWN:
- LMB = 1;
- break;
- case MENUUP:
- RMB = 0;
- break;
- case MENUDOWN:
- RMB = 1;
- break;
- case MIDDLEUP:
- MMB = 0;
- break;
- case MIDDLEDOWN:
- MMB = 1;
- break;
- }
- break;
- }
- ReplyMsg((struct Message *)message);
- }
- }
-
- static void
- StripIntuiMessages(struct MsgPort *mp, struct Window *win)
- {
- struct IntuiMessage *msg;
- struct Node *succ;
-
- msg = (struct IntuiMessage *)mp->mp_MsgList.lh_Head;
-
- while (succ = msg->ExecMessage.mn_Node.ln_Succ) {
- if (msg->IDCMPWindow == win) {
- Remove((struct Node*)msg);
- ReplyMsg((struct Message *)msg);
- }
- msg = (struct IntuiMessage *)succ;
- }
- }
-
- static struct MsgPort *
- CreatePort(UBYTE *name, LONG pri)
- {
- struct MsgPort *newmp;
-
- if (newmp = CreateMsgPort()) {
- newmp->mp_Node.ln_Name = name;
- newmp->mp_Node.ln_Pri = pri;
- AddPort(newmp);
- }
- return newmp;
- }
-
- static void
- DeletePort(struct MsgPort *mp)
- {
- if (mp) {
- if (mp->mp_Node.ln_Name) {
- RemPort(mp);
- }
- DeleteMsgPort(mp);
- }
- }
-